package work.thread_eg.thread0.pool0;

import java.util.concurrent.*;


/**
 * callable接口 +  线程池ExecutorService  实现多线程
 *
 * 线程池 ExecutorService 返回值
 * 两种用法
 * 1 通过submit() 提交Callable接口的线程类 得到Future
 * 2 提前创建 FutureTask对象 使用execute(FutureTask) 再从FutureTask对象获取结果
 *      如果FutureTask对象是通过 Callable接口的实现类创建的 get返回值就是call()方法的返回值
 *      如果FutureTask对象是通过 Runnable接口的实现类创建的 get返回值就是FutureTask构造函数的第二个参数的值
 *
 */
public class CallablePool {
    public static void main(String[] args) {
        CallablePool callablePool = new CallablePool();

        // 执行任务
        callablePool.work();
    }

    public void work() {
        // 开始时间
        long begin = System.currentTimeMillis();

        // 可缓存线程池
        ExecutorService threadPool = Executors.newCachedThreadPool();

        // 实现了Callable接口的线程类
        AddCallable callable01 = new AddCallable("Task-01", 1, 50);
        AddCallable callable02 = new AddCallable("Task-02", 51, 100);
        AddCallable callable03 = new AddCallable("Task-03", 1, 10);

        // 1 线程池submit() 提交任务 也就是执行线程任务 得到Future对象
        // Future接口的默认实现类是FutureTask
        Future<Long> future1 = threadPool.submit(callable01);
        Future<Long> future2 = threadPool.submit(callable02);

        // 2 线程池execute() 执行任务 结果会保存到提前创建好的FutureTask对象中
        FutureTask<Long> futureTask3 = new FutureTask<>(callable03);
        threadPool.execute(futureTask3);

        try {
            // get方法会阻塞主线程
            Long sum1 = future1.get();
            Long sum2 = future2.get();
            Long sum3 = futureTask3.get();
            System.out.println("线程1 的结果：" + sum1);
            System.out.println("线程2 的结果：" + sum2);
            System.out.println("线程3 的结果：" + sum3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            threadPool.shutdown();
        }

        // 结束时间
        System.out.println(System.currentTimeMillis() - begin + "毫秒");
    }

    /**
     * 线程类
     * 累计任务
     *
     * Callable<Long>  Long指定异步任务返回结果的类型
     *
     */
    static class AddCallable implements Callable<Long> {
        private final String name;
        private final long begin;
        private final long end;

        public AddCallable(String name, long begin, long end) {
            this.name = name;
            this.begin = begin;
            this.end = end;
        }

        /**
         * 累加计算
         *
         * @return
         * @throws Exception
         */
        @Override
        public Long call() throws Exception {
            System.out.println("当前执行线程的名字: " + Thread.currentThread().getName());
            long sum = 0;
            for (long i = begin; i <= end; i++) {
                sum += i;
            }
            return sum;
        }
    }

}
